<?php
/**
 *  后台代理customer的职员管理
 * Author: lyun
 * Date: 2018/3/30
 * Created by Panxsoft.
 */


namespace App\Http\Controllers\Admin\Customer;

use App\Http\Controllers\ApiController;
use App\Http\Middleware\CustomerAuth;
use App\Http\Requests\Admin\Customer\StaffIndexRequest;
use App\Http\Requests\Admin\Customer\StaffOperateRequest;
use App\Http\Requests\Admin\Customer\StaffStoreRequest;
use App\Http\Requests\Admin\Customer\StaffUpdateRequest;
use App\Models\Admin\CustomerAdmin;
use App\Services\Locale\Language;
use App\Services\Utils\Guard;
use App\Services\Utils\Transaction;
use Carbon\Carbon;
use Illuminate\Http\Request;
use App\Models\Admin\Role;

class CustomerStaffController extends ApiController
{
    const ROUTES = [
        'index'   => 'api.admin.customer.staff.index',
        'store'   => 'api.admin.customer.staff.store',
        'update'  => 'api.admin.customer.staff.update',
        'patch'   => 'api.admin.customer.staff.patch',
    ];

    /**
     * Display a listing of the resource.
     * @test
     *
     * @param StaffIndexRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function index(StaffIndexRequest $request)
    {
        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        // 显示所有，除了自己
        $customer_admin = CustomerAdmin::filterIsSuperMan()
            ->columnsKeywordsOrLike([
                'name'    => $request->keyword,
                'account' => $request->keyword,
                'email'   => $request->keyword,
                'phone'   => $request->keyword,
            ])
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->with('roles')
            ->orderBy($request->order_by ?? 'created_at', $request->sort ?? 'desc')
            ->paginate($request->per_page ?: 15);

        return $this->response(compact('customer_admin'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $roles = Role::where('guard_name', CustomerAdmin::GUARD_NAME)
            ->where('is_deleted', Role::ROLE_IS_NOT_DELETED)
            ->get(['id', Language::getLocalNameColumn()]);

        return $this->response(compact('roles'));
    }

    /**
     * Store a newly created resource in storage.
     * @test
     *
     * @param  StaffStoreRequest $request
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function store(StaffStoreRequest $request)
    {
        // 超管才能添加的
        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(), trans('admin.is_super_man'));

        $customer_admin = $this->assembleStaffStoreData($request);
        $role_name = $this->getChineseRole($request->role_name);

        $stored = Transaction::handle(function () use ($role_name, $customer_admin) {

            /** @var CustomerAdmin $customer */
            $customer = CustomerAdmin::create($customer_admin);

            $customer->assignRole($role_name);

            return $customer;
        });

        return $this->response(compact('stored'));
    }

    /**
     * 更新自己 和 超管更新职员的信息
     * @test
     *
     * @param  StaffUpdateRequest $request
     * @param  int $id
     * @return \Illuminate\Http\Response
     * @throws \Exception
     */
    public function update(StaffUpdateRequest $request, $id)
    {
        /** @var CustomerAdmin $customer_admin */
        $customer_admin = (new CustomerAdmin)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($id);
        $this->checkItemExist($customer_admin, trans('admin.customer_admin'));

        $customer_admin_data = $this->assembleStaffStoreData($request);

        $is_super_man = CustomerAdmin::isGuardSuperAdmin();
        $is_update_self = (Guard::customerAdmin()->id === (int)$id);

        if ($is_update_self) { // 更新自己

            $updated = $customer_admin->update($customer_admin_data);
        } else if ($is_super_man) {  // 超管更新职员

            $updated = $this->updateCustomerStaff($customer_admin, $customer_admin_data, $request->role_name);
        } else {

            $this->checkIsTrue(false, trans('admin.illegality_customer_admin'));
        }

        $customer_admin = $customer_admin->load('Roles');

        return $this->response(compact('updated', 'customer_admin'));
    }

    /**
     * @deprecated (废弃，改成启用和禁用了)
     *
     * Remove the specified resource from storage.
     *
     * @param  int $id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function destroy($id)
    {
        $this->checkIsTrue($id !== Guard::customerAdmin()->id, '管理员不能删除自己');
        $this->checkIsTrue(Guard::customerAdmin()->isSuperMan(), '只有管理员能删除员工');

        /** @var CustomerAdmin $staff */
        $staff = (new CustomerAdmin)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->find($id);
        $this->checkIsTrue($staff, '错误的管理员ID');

        $deleted = $staff->delete();

        return $this->response(compact('deleted'));
    }

    /**
     * 启用和禁用后台管理员
     * @test
     *
     * @param StaffOperateRequest $request
     * @param string $staff_id
     * @return array|\Illuminate\Http\Response
     * @throws \Exception
     */
    public function patchEnabled(StaffOperateRequest $request, $staff_id)
    {
        // 超管才能操作的
        $this->checkIsTrue(CustomerAdmin::isGuardSuperAdmin(),  trans('admin.is_super_man'));

        // 不能禁用第一个超管
        $first_customer_admin = (new CustomerAdmin)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->oldest()
            ->first();
        $this->checkUnless($first_customer_admin->id === (int)$staff_id, trans('admin.first_customer_admin'));

        /** @var CustomerAdmin $edit_staff */
        $guard_customer_id = Guard::customerAdmin()->customer_id;
        $edit_staff = (new CustomerAdmin)
            ->where('customer_id', $guard_customer_id)
            ->find($staff_id);
        $this->checkCanPatchStatus($edit_staff);

        $updated = $edit_staff->update(['is_deleted' => $request->is_deleted]);

        return $this->response(compact('updated', 'edit_staff'));
    }

    /**
     * @param StaffStoreRequest|StaffUpdateRequest|Request $request
     * @return array
     */
    private function assembleStaffStoreData(Request $request)
    {
        $data = [
            'customer_id' => Guard::customerAdmin()->customer_id,
            'name'        => $request->name,
            'email'       => $request->email,
            'account'     => $request->account,
            'phone'       => $request->phone,
            'sex'         => $request->sex,
            'born_at'     => $request->born_at ?? Carbon::now(),
        ];

        if ($request->password) {
            $data['password'] = $request->password;
        }

        return $data;
    }

    /**
     * @param $role_name
     * @return null
     * @throws \Exception
     */
    private function getChineseRole($role_name)
    {
        if (! Language::appIsCN()) {
            $role_name = CustomerAdmin::ROLE_EN_TO_CN_MAP[$role_name] ?? null;
            $this->checkIsTrue($role_name, trans('admin.role_name'));
        }

        return $role_name;
    }

    /**
     * @param $edit_staff
     * @throws \Exception
     */
    private function checkCanPatchStatus(?CustomerAdmin $edit_staff): void
    {
        $this->checkItemExist(Guard::customerAdmin(), trans('admin.customer_admin'));
        $this->checkCanOperate(Guard::customerAdmin()->hasRole(CustomerAdmin::SUPER_MAN), trans('admin.customer_admin_not_super_man'));
        $this->checkCanOperate($edit_staff->id !== Guard::customerAdmin()->id, trans('admin.edit_staff'));
    }

    /**
     * @param CustomerAdmin $customer_admin
     * @param array $customer_admin_data
     * @param $role_name
     * @return mixed
     * @throws \Exception
     */
    private function updateCustomerStaff(CustomerAdmin $customer_admin, array $customer_admin_data, $role_name)
    {
        $updated = Transaction::handle(function () use ($customer_admin, $customer_admin_data, $role_name) {

            $this->editStaffRole($customer_admin, $role_name);

            $customer_admin->update($customer_admin_data);

            return $customer_admin;
        });

        return $updated;
    }

    /**
     * @param CustomerAdmin $customer_admin
     * @param $role_name
     * @return bool
     * @throws \Exception
     */
    private function editStaffRole(CustomerAdmin $customer_admin, $role_name)
    {
        if (!$role_name) return true;

        $role_name = $this->getChineseRole($role_name);

        //不能修改第一个超管的角色
        $first_customer_admin = (new CustomerAdmin)
            ->where('customer_id', Guard::customerAdmin()->customer_id)
            ->oldest()
            ->first();

        $admin_is_oldest = $first_customer_admin->id === $customer_admin->id;
        $admin_had_role = $customer_admin->hasRole($role_name);

        if ($admin_is_oldest ) {
            $this->checkIsTrue($admin_had_role, trans('admin.first_customer_admin'));

            return true;
        }

        $customer_admin->syncRoles($role_name);

        return true;
    }
}
